<?php
use oxide\data\model\DataObject;
require LIB_DIR . "/oxide/DataObject.php";

/**
 * Base Data model class for the yasns project
 *
 * provides varies ways to store/access data
 * basic database operations
 * All database table should extend this class
 */
class DataModel extends DataObject
{
	/**
	 *
	 * @access protected
	 */
	protected 
			  $_table,
			  $_pk,
			  $_isLoaded;
	
	/**
	 *
	 * @access protected static
	 */
	protected static
			  $_connection;
	

	/**
	 * initialize the model
	 *
	 * if primary key is given, data will be loaded from the database
	 * use this to load row or create a new row in the database
	 * @param string $pk 
	 */
	public function __construct($pk = null) 
	{
		parent::__construct(null);
		
		// if $pk exists, trigger _load function
		if($pk) $this->_load($pk);		
	}
	
	/**
	 * Set database connection
	 *
	 * this connection will be used by all data model objects
	 * connection should be set when application initializes (ActionController initialization)
	 * @param oxide\data\Connection $connection 
	 */
	public static function setConnection($connection)
	{
		self::$_connection = $connection;
	}
	
	/**
	 * Get database connection
	 * @return oxide\data\Connection 
	 */
	public static function getConnection()
	{
		return self::$_connection;
	}
	
	/**
	 * Return query results based on pk, and flag $_isLoaded
	 * @param int $pk 
	 */
	protected function _load($pk)
	{
		$conn = self::getConnection();
		$where = $this->_pk .' = ' . $pk;
		$stmt = $conn->query("select * from ". $this->_table ." where " . $where);
		
		$row = $stmt->fetch();
		
		if ($row) {
			$this->_isLoaded = true;
			$this->setData($row);
		} else {
			$this->_isLoaded = false;
		}
	}
	
	/**
	 * Check flag value to see if data object has been initialized from the database
	 *
	 * @return boolean 
	 */
	public function isLoaded()
	{
		return $this->_isLoaded;
	}
	
	/**
	 * insert data into database
	 *
	 * adds a new data row in the associated table witin database
	 * assigns the primary key back to the data object
	 * returns primary key for the newly created data object
	 * @return int 
	 */
	public function insert()
	{
		$conn = $this->getConnection();
		$data = $this->getModifiedData();
		
		
		$conn->insert($this->_table, $data);
		
		// getting the primary key
		$pkval = $conn->lastInsertId();
		
		// setting up the primary key
		$pkcol = $this->_pk;
		$this->$pkcol =  $pkval;
		
		return $pkval;
	}
	
	/**
	 * Update data into database 
	 *
	 * primary key must be associated with the object model
	 * object will only be updated if there is any modification
	 * @return boolean
	 */
	public function update()
	{
		$conn = $this->getConnection();
		$data = $this->getModifiedData();
		
		if (!$this->isModified()) return false;

		$pkcol = $this->_pk;
		$pkval = $this->$pkcol;
		
		if(!$pkval) throw new Exception('Primary key is not associated with this object');
		$where = "{$pkcol} = :{$pkcol}";

		$conn->update($this->_table, $data, $where, array($pkcol => $pkval));

		return true;
		
	}
	
	/**
	 * Delete data from database
	 * primary key must be associated with the object model
	 */
	public function delete()
	{
		$conn = $this->getConnection();
		$pkcol = $this->_pk;
		$pkval = $this->$pkcol;
		
		if(!$pkval) throw new Exception('Primary key is not associated with this object');

		$where = "{$pkcol} = ?";
		$conn->delete($this->_table, $where, array($pkcol => $pkval));
	}
}
?>
